package com.server.common.logistics.dsf;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.google.gson.reflect.TypeToken;
import com.server.common.code.utils.GsonUtils;
import com.server.common.logistics.base.BaseLogisticsService;
import com.server.common.logistics.dsf.create.DSFCreateOrderRequest;
import com.server.common.logistics.dsf.create.DSFCreateOrderResponse;
import com.server.common.logistics.dsf.enums.DSFApiEnum;
import com.server.common.logistics.dsf.get.DSFGetOrderRequest;
import com.server.common.logistics.dsf.get.DSFGetOrderResponse;
import com.server.common.logistics.dsf.hold.DSFHoldOrderRequest;
import com.server.common.logistics.dsf.hold.DSFHoldOrderResponse;
import com.server.common.logistics.dsf.printLabel.DSFPrintLabelRequest;
import com.server.common.logistics.dsf.track.DSFGetTrackResponse;
import com.server.common.logistics.enums.ApiEnum;
import com.server.common.logistics.enums.LogisticsCompanyEnum;
import com.server.common.logistics.request.LogisticsRequest;
import com.server.common.logistics.result.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;

@Component
@Slf4j
public class DSFServiceImpl extends BaseLogisticsService {

    @Resource
    private DSFConfig dsfConfig;

    @Override
    public LogisticsCompanyEnum getLogisticsCompanyEnum() {
        return LogisticsCompanyEnum.DSF;
    }

    @Override
    public  <T> DSFOrderResponse<T> baseRequest(ApiEnum apiEnum, Object params){
        //公共参数
        Map<String, Object> publicParamsMap = new HashMap<>();
        publicParamsMap.put("method", apiEnum.getMethod());
        publicParamsMap.put("app_key", dsfConfig.getAppKey());
        publicParamsMap.put("v", apiEnum.getVersion());
        publicParamsMap.put("timestamp", System.currentTimeMillis());
        publicParamsMap.put("format", "json");

        TreeMap treeMap = GsonUtils.getGson().fromJson(GsonUtils.getGson().toJson(params), TreeMap.class);

        String signStr = MapUtil.sortJoin(publicParamsMap, StrUtil.EMPTY, StrUtil.EMPTY, true);

        String paramsJson = JSONUtil.toJsonStr(treeMap);

        signStr = signStr + paramsJson + dsfConfig.getAppSecret();
        String sign = SecureUtil.md5(signStr);
        publicParamsMap.put("sign", sign);

        String formData = MapUtil.sortJoin(publicParamsMap, "&", "=", true);

        HttpRequest request = HttpUtil.createPost(dsfConfig.getUrl() + "?" + formData);
        request.body(paramsJson);

        String body = request.execute().body();

        return GsonUtils.getGson().fromJson(body,new TypeToken<DSFOrderResponse<T>>(){}.getType());
    }

    @Override
    public CreateOrderResult createOrder(LogisticsRequest orderRequest) {
        CreateOrderResult createOrderResult = new CreateOrderResult();

        try {
            if(!(orderRequest instanceof DSFCreateOrderRequest)){
                createOrderResult.setErrorMsg("递四方订单参数有误");
                return createOrderResult;
            }
            DSFOrderResponse<DSFCreateOrderResponse> dsfOrderResponse = baseRequest(DSFApiEnum.CREATE_ORDER, orderRequest);

            if(!dsfOrderResponse.responseOk()){
                createOrderResult.setErrorMsg(dsfOrderResponse.getMsg());
                return createOrderResult;
            }

            if(dsfOrderResponse.dataEmpty()){
                createOrderResult.setErrorMsg("下单失败");
                return createOrderResult;
            }
            DSFCreateOrderResponse data = dsfOrderResponse.getData();

            createOrderResult.setThirdOrderId(UUID.randomUUID().toString().replace("-",""));
            createOrderResult.setTrackingNumber(data.getTrackingNumber());
            createOrderResult.setErrorMsg(dsfOrderResponse.getMsg());
            createOrderResult.setTransferBillNo(dsfOrderResponse.getData().getTransferBillNo());
        }catch (Exception e){
            log.error("下单失败",e);
            createOrderResult.setErrorMsg("下单失败");
        }

        return createOrderResult;
    }

    @Override
    public GetOrderResult getOrder(LogisticsRequest orderRequest) {
        GetOrderResult getOrderResult = new GetOrderResult();

        try {
            if(!(orderRequest instanceof DSFGetOrderRequest)){
                getOrderResult.setErrorMsg("递四方订单获取参数有误");
                return getOrderResult;
            }

            DSFOrderResponse<List<DSFGetOrderResponse>> dsfOrderResponse = baseRequest(DSFApiEnum.GET_ORDER, orderRequest);

            if(!dsfOrderResponse.responseOk()){
                getOrderResult.setErrorMsg(dsfOrderResponse.getMsg());
                return getOrderResult;
            }

            if(dsfOrderResponse.dataEmpty()){
                getOrderResult.setErrorMsg("递四方订单不存在");
                return getOrderResult;
            }
            List<DSFGetOrderResponse> dataList = dsfOrderResponse.getData();

            DSFGetOrderResponse data = CollUtil.getFirst(dataList);
            if(ObjectUtils.isEmpty(data)){
                getOrderResult.setErrorMsg("递四方订单不存在");
                return getOrderResult;
            }

            DSFGetOrderResponse.ConsignmentInfo consignmentInfo = data.getConsignmentInfo();
            if(ObjectUtils.isEmpty(consignmentInfo)){
                getOrderResult.setErrorMsg("递四方订单的货物信息不存在");
                return getOrderResult;
            }

            getOrderResult.setTrackingNumber(consignmentInfo.getTrackingNumber());
            getOrderResult.setTransferBillNo(consignmentInfo.getTransferBillNo());
        }catch (Exception e){
            log.error("递四方获取订单失败",e);
            getOrderResult.setErrorMsg("递四方获取订单失败");
        }
        return getOrderResult;
    }

    @Override
    public HoldOrderResult holdOrder(LogisticsRequest holdOrderRequest) {
        HoldOrderResult holdOrderResult = new HoldOrderResult();

        try {
            if(!(holdOrderRequest instanceof DSFHoldOrderRequest)){
                holdOrderResult.setErrorMsg("递四方拦截订单参数有误");
                return holdOrderResult;
            }

            DSFOrderResponse<DSFHoldOrderResponse> dsfOrderResponse = baseRequest(DSFApiEnum.HOLD_ORDER, holdOrderRequest);

            holdOrderResult.setHoldFlag(dsfOrderResponse.responseOk());
            holdOrderResult.setErrorMsg(dsfOrderResponse.getMsg());
        }catch (Exception e){
            log.error("holdOrderResult",e);
            holdOrderResult.setErrorMsg("递四方拦截订单失败");
        }

        return holdOrderResult;
    }

    @Override
    public GetTrackResult getTracking(LogisticsRequest getTrackRequest) {
        GetTrackResult getTrackResult = new GetTrackResult();

        try {
            if(!(getTrackRequest instanceof DSFHoldOrderRequest)){
                getTrackResult.setErrorMsg("递四方物流轨迹参数有误");
                return getTrackResult;
            }

            DSFOrderResponse<DSFGetTrackResponse> dsfOrderResponse = baseRequest(DSFApiEnum.GET_TRACK, getTrackRequest);

            if(!dsfOrderResponse.responseOk()){
                getTrackResult.setErrorMsg(dsfOrderResponse.getMsg());
                return getTrackResult;
            }

            if(dsfOrderResponse.dataEmpty()){
                getTrackResult.setErrorMsg("获取物流轨迹失败");
                return getTrackResult;
            }

            DSFGetTrackResponse data = dsfOrderResponse.getData();

            getTrackResult.setTrackingNumber(data.getTrackingNumber());
            getTrackResult.setDestinationCountry(data.getDestinationCountry());

            List<DSFGetTrackResponse.Tracking> trackingList = data.getTrackingList();
            if(ObjectUtils.isEmpty(trackingList)){
                getTrackResult.setTackList(new ArrayList<>());
                return getTrackResult;
            }

            //起始时间
            DSFGetTrackResponse.Tracking startTackBean = CollUtil.getFirst(trackingList);
            //最后一个物流时间
            DSFGetTrackResponse.Tracking overTackBean = CollUtil.getLast(trackingList);
            //运输时间
            long transitDay = DateUtil.between(DateUtil.parseDate(startTackBean.getOccurDatetime()), DateUtil.parseDate(overTackBean.getOccurDatetime()),DateUnit.DAY);
            getTrackResult.setTransitDay((int) Math.max(transitDay,0));

            //停留时间
            long stayDay = DateUtil.between(DateUtil.parseDate(overTackBean.getOccurDatetime()), DateUtil.date(),DateUnit.DAY);
            getTrackResult.setStayDay((int) Math.max(stayDay,0));

            //
            for (DSFGetTrackResponse.Tracking tracking :trackingList){
                GetTrackResult.Tack tack = new GetTrackResult.Tack();
                tack.setTime(tracking.getOccurDatetime());
                tack.setContent(tracking.getTrackingContent());
                tack.setLocation(tracking.getOccurLocation());
                tack.setStatusCode(tracking.getBusinessLinkCode());
                getTrackResult.getTackList().add(tack);
            }
        }catch (Exception e){
            log.error("获取物流轨迹失败",e);
            getTrackResult.setErrorMsg("获取物流轨迹失败");
        }

        return getTrackResult;
    }

    @Override
    public PrintLabelSyncResult printLabelSync(LogisticsRequest printLabelSyncRequest) {
        PrintLabelSyncResult printLabelSyncResult = new PrintLabelSyncResult();

        try {
            if(!(printLabelSyncRequest instanceof DSFPrintLabelRequest)){
                printLabelSyncResult.setErrorMsg("打印面单请求参数有误");
                return printLabelSyncResult;
            }

            DSFPrintLabelRequest dsfPrintLabelRequest = (DSFPrintLabelRequest) printLabelSyncRequest;
            dsfPrintLabelRequest.setLabelSize("label_100x150");
            DSFOrderResponse<String> dsfOrderResponse = baseRequest(DSFApiEnum.PRINT_LABEL, dsfPrintLabelRequest);

            if(!dsfOrderResponse.responseOk()){
                printLabelSyncResult.setErrorMsg(dsfOrderResponse.getMsg());
                return printLabelSyncResult;
            }

            if(!dsfOrderResponse.dataEmpty()){
                printLabelSyncResult.setErrorMsg("打印面单失败");
                return printLabelSyncResult;
            }

            HttpRequest httpRequest = HttpUtil.createGet(dsfOrderResponse.getData());

            //10s的下载时间
            httpRequest.timeout(1000*10);
            byte[] bytes = httpRequest.execute().bodyBytes();
            printLabelSyncResult.setBytes(bytes);
        }catch (Exception e){
            log.error("打印面单失败",e);
            printLabelSyncResult.setErrorMsg("打印面单失败");
        }

        return printLabelSyncResult;
    }

}
